import 'dart:async';

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

class TimerPage extends StatefulWidget {
  final String title;

  TimerPage(this.title);

  @override
  State<StatefulWidget> createState() {
    return new _TimerPageState();
  }
}

class _TimerPageState extends State<TimerPage> {
  TimerUtil mTimerUtil;
  TimerUtil mCountDownTimerUtil;

  int mTick = 0;
  String timerBtnTxt = "Start";

  int mCountDownTick = 0;
  String countDownBtnTxt = "Start";

  @override
  void initState() {
    super.initState();
    mTimerUtil = new TimerUtil(mInterval: 1000);
    //mTimerUtil.setInterval(1000);
    mTimerUtil.setOnTimerTickCallback((int tick) {
      setState(() {
        mTick = tick;
      });
    });

    mCountDownTimerUtil = new TimerUtil(mInterval: 1000, mTotalTime: 6 * 1000);
//    mCountDownTimerUtil.setInterval(1000);
//    mCountDownTimerUtil.setTotalTime(6 * 1000);
    mCountDownTimerUtil.setOnTimerTickCallback((int tick) {
      double _tick = tick / 1000;
      if (_tick.toInt() == 0) {
        countDownBtnTxt = "Start";
        mCountDownTimerUtil.setTotalTime(6 * 1000);
      }
      setState(() {
        mCountDownTick = _tick.toInt();
      });
    });
  }

  @override
  void dispose() {
    super.dispose();
    if (mTimerUtil != null) mTimerUtil.cancel();
    if (mCountDownTimerUtil != null) mCountDownTimerUtil.cancel();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
        centerTitle: true,
      ),
      body: new Column(
        children: <Widget>[
          new Card(
            elevation: 4.0,
            margin: const EdgeInsets.all(10.0),
            child: new Container(
              alignment: Alignment.center,
              child: new Column(
                children: <Widget>[
                  new Container(
                    color: Colors.grey[50],
                    height: 100.0,
                    child: new Row(
                      children: <Widget>[
                        new Container(
                          width: 100.0,
                          height: 100.0,
                          color: Colors.grey[100],
                          alignment: Alignment.center,
                          child: new Text("Timer"),
                        ),
                        new Expanded(
                          child: new Container(
                            alignment: Alignment.center,
                            child: new Text('$mTick'),
                          ),
                          flex: 1,
                        ),
                        new InkWell(
                            child: new Container(
                              width: 100.0,
                              height: 100.0,
                              color: Colors.grey[100],
                              alignment: Alignment.center,
                              child: new Text("$timerBtnTxt"),
                            ),
                            onTap: () {
                              if (mTimerUtil.isActive()) {
                                mTick = 0;
                                mTimerUtil.cancel();
                                timerBtnTxt = "Start";
                              } else {
                                mTimerUtil.startTimer();
                                timerBtnTxt = "Stop";
                              }
                              setState(() {});
                            })
                      ],
                    ),
                  ),
                  new Container(
                    margin: const EdgeInsets.only(top: 10.0),
                    color: Colors.grey[50],
                    height: 100.0,
                    child: new Row(
                      children: <Widget>[
                        new Container(
                          width: 100.0,
                          height: 100.0,
                          color: Colors.grey[100],
                          alignment: Alignment.center,
                          child: new Text("CountDown"),
                        ),
                        new Expanded(
                          child: new Container(
                            alignment: Alignment.center,
                            child: new Text('$mCountDownTick'),
                          ),
                          flex: 1,
                        ),
                        new InkWell(
                            child: new Container(
                              width: 100.0,
                              height: 100.0,
                              color: Colors.grey[100],
                              alignment: Alignment.center,
                              child: new Text("$countDownBtnTxt"),
                            ),
                            onTap: () {
                              if (mCountDownTimerUtil.isActive()) {
                                mCountDownTimerUtil.cancel();
                                countDownBtnTxt = "Start";
                              } else {
                                mCountDownTimerUtil.startCountDown();
                                countDownBtnTxt = "Stop";
                              }
                              setState(() {});
                            })
                      ],
                    ),
                  ),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}

///timer callback.(millisUntilFinished 毫秒).
typedef void OnTimerTickCallback(int millisUntilFinished);

/**
 * @Author: Sky24n
 * @GitHub: https://github.com/Sky24n
 * @Description: Timer Util.
 * @Date: 2018/9/28
 */

/// TimerUtil.
class TimerUtil {
  TimerUtil({this.mInterval = Duration.millisecondsPerSecond, this.mTotalTime});

  /// Timer.
  Timer _mTimer;

  /// Is Timer active.
  /// Timer是否启动.
  bool _isActive = false;

  /// Timer interval (unit millisecond，def: 1000 millisecond).
  /// Timer间隔 单位毫秒，默认1000毫秒(1秒).
  int mInterval;

  /// countdown totalTime.
  /// 倒计时总时间
  int mTotalTime; //单位毫秒

  OnTimerTickCallback _onTimerTickCallback;

  /// set Timer interval. (unit millisecond).
  /// 设置Timer间隔.
  void setInterval(int interval) {
    if (interval <= 0) interval = Duration.millisecondsPerSecond;
    mInterval = interval;
  }

  /// set countdown totalTime. (unit millisecond).
  /// 设置倒计时总时间.
  void setTotalTime(int totalTime) {
    if (totalTime <= 0) return;
    mTotalTime = totalTime;
  }

  /// start Timer.
  /// 启动定时Timer.
  void startTimer() {
    if (_isActive || mInterval <= 0) return;
    _isActive = true;
    Duration duration = Duration(milliseconds: mInterval);
    _doCallback(0);
    _mTimer = Timer.periodic(duration, (Timer timer) {
      _doCallback(timer.tick);
    });
  }

  /// start countdown Timer.
  /// 启动倒计时Timer.
  void startCountDown() {
    if (_isActive || mInterval <= 0 || mTotalTime <= 0) return;
    _isActive = true;
    Duration duration = Duration(milliseconds: mInterval);
    _doCallback(mTotalTime);
    _mTimer = Timer.periodic(duration, (Timer timer) {
      int time = mTotalTime - mInterval;
      mTotalTime = time;
      if (time >= mInterval) {
        _doCallback(time);
      } else if (time == 0) {
        _doCallback(time);
        cancel();
      } else {
        timer.cancel();
        Future.delayed(Duration(milliseconds: time), () {
          mTotalTime = 0;
          _doCallback(0);
          cancel();
        });
      }
    });
  }

  void _doCallback(int time) {
    if (_onTimerTickCallback != null) {
      _onTimerTickCallback(time);
    }
  }

  /// update countdown totalTime.
  /// 重设倒计时总时间.
  void updateTotalTime(int totalTime) {
    cancel();
    mTotalTime = totalTime;
    startCountDown();
  }

  /// timer is Active.
  /// Timer是否启动.
  bool isActive() {
    return _isActive;
  }

  /// Cancels the timer.
  /// 取消计时器.
  void cancel() {
    if (_mTimer != null) {
      _mTimer.cancel();
      _mTimer = null;
    }
    _isActive = false;
  }

  /// set timer callback.
  void setOnTimerTickCallback(OnTimerTickCallback callback) {
    _onTimerTickCallback = callback;
  }
}
